home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Scene Storm
/
Scene Storm - Volume 1.iso
/
coding
/
c
/
jpegagasrc
/
jpegaga
/
jpegaga.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-08
|
21KB
|
792 lines
/* jpegAGA 2.2 written by Günther Röhrich */
#define __NOLIBBASE__
#include <workbench/startup.h>
#include <proto/dos.h>
#include "WBFlags.h"
#include <stdio.h>
#include <stdlib.h>
/*
* Include file for users of JPEG library.
* You will need to have included system headers that define at least
* the typedefs FILE and size_t before you can include jpeglib.h.
* (stdio.h is sufficient on ANSI-conforming systems.)
* You may also wish to include "jerror.h".
*/
#include "jpeglib.h"
#include "jerror.h"
#include "myerror.h"
#define JMAKE_MSG_TABLE
#include "myerror.h" /* create the message string table */
/*
* <setjmp.h> is used for the optional error recovery mechanism shown in
* the second part of the example.
*/
#include <setjmp.h>
#include <signal.h>
#include <string.h>
extern void Amiga_jpeg_stdio_src (j_decompress_ptr cinfo, BPTR infile);
#define HAM8 1
/* #define DEBUGFILE */ /* write a ppm file for debugging */
#ifdef __GNUC__
#define MYSTRCMP strcasecmp
#define MYSTRNCMP strncasecmp
#else
#define MYSTRCMP strcmp
#define MYSTRNCMP strncmp
#endif
#define MAXFILES 500
char *ver = "\0$VER: jpegAGA 2.2 (15.9.95)";
#ifdef __GNUC__
char __stdiowin[]="CON:30/12/600/80/jpegAGA 2.2";
#endif
struct WBFlags WBFlags =
{
1, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
struct WBFlags OldFlags;
short SMR_HAM;
short WBFiles=0;
short DoNotWait=0;
short finish=0;
static short ButtonPressed=0;
BPTR olddir=0;
int NumPictures=0;
struct WBArg *wb_arg=NULL;
char *PicArray[MAXFILES];
unsigned long SMR_DisplayID = 0;
unsigned long *ScreenColorTable=NULL;
short ASLPicSelect = 0;
static unsigned long Mode=0;
static char *MapFileName=NULL;
static char *MapDirName=NULL;
static BPTR infile=0;
static BPTR ColorMapFile = 0;
/* This struct contains the JPEG decompression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
*/
static struct jpeg_decompress_struct cinfo;
/* We use our private extension JPEG error handler. */
static struct jpeg_error_mgr jerr;
volatile int PictureNr;
extern void FillNameBuffer(char *pattern);
extern void ParseToolTypes(struct WBArg *wbarg, int initial);
extern int InitDisplay(int cols, int rows, unsigned long Mode, int NumPlanes);
extern void CloseDisplay(void);
extern void DisplayRow(JSAMPROW buffer, int cols);
extern int CheckButton(void);
extern void FinalWait(void);
extern void FlipScreen(void);
extern void FreeASL(void);
extern int ChooseScreenMode(int grayscale, char *title);
extern void ChooseFiles(void);
extern int FindScaleFit(JDIMENSION width, JDIMENSION height, unsigned long Mode);
extern unsigned long my_screen[2];
extern unsigned long ScaleFitDisplayID;
JSAMPROW OutputBuffer=NULL;
extern void EncodeHAM8(JSAMPROW orig, JSAMPROW yham, int xsize);
unsigned short Mult_Table[2*256];
jmp_buf setjmp_buffer;
/* NOTE: this array is in brgbrg order */
char *ColorCache=NULL;
unsigned char FixedColorTable[64*3] =
{ 0, 0, 0, 4, 4, 4, 8, 8, 8, 12,12,12,
16,16,16, 20,20,20, 24,24,24, 28,28,28, /* 16 colors */
32,32,32, 36,36,36, 41,41,41, 46,46,46,
51,51,51, 55,55,55, 59,59,59, 63,63,63,
17,17,39, 17,17,55, /* 13 colors */
17,29,17, 17,29,39, 17,29,55,
17,39,17, 17,39,29, 17,39,39, 17,39,55,
17,55,17, 17,55,39, 17,55,39, 17,55,55,
29,17,29, 29,17,39, 29,17,55, /* 11 colors */
29,29,55,
29,39,17, 29,39,29, 29,39,55,
29,55,17, 29,55,29, 29,55,39, 29,55,55,
39,17,17, 39,17,29, 39,17,39, 39,17,55, /* 12 colors */
39,29,17, 39,29,29, 39,29,55,
39,39,17, 39,39,29,
39,55,17, 39,55,29,
55,17,17, 55,17,29, 55,17,39, 55,17,55, /* 13 colors */
55,29,27, 55,29,29, 55,29,39, 55,29,55,
55,39,17, 55,39,29, 55,39,39,
55,55,17, 55,55,29
};
unsigned char ColorTable[64*3];
METHODDEF void
my_error_exit (j_common_ptr cinfo)
{
#ifdef __GNUC__
signal(SIGINT, SIG_IGN);
#endif
/* Always display the message. */
if(cinfo->err->msg_code != JWRN_JPEGAGA_STOPPED) (*cinfo->err->output_message) (cinfo);
/* Return control to the setjmp point */
longjmp(setjmp_buffer, 1);
}
void interrupt(int signum)
{
#ifdef __GNUC__
signal(SIGINT, SIG_IGN);
#endif
printf("^C\n");
ButtonPressed = 1;
longjmp(setjmp_buffer, 1);
}
GLOBAL int
read_JPEG_file (char *filenames[])
{
/* More stuff */
JSAMPARRAY buffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
int DisplaySuccess, i;
char *filename;
/* Step 1: allocate and initialize JPEG decompression object */
jpeg_create_decompress(&cinfo);
/* Now we can initialize the JPEG decompression object. */
/* We set up the normal JPEG error routines, then override error_exit. */
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = my_error_exit;
/* Set maximum memory to use */
if(WBFlags.MaxMemFlag) cinfo.mem->max_memory_to_use = WBFlags.MaxMem * 1000L;
/* Add some application-specific error messages (from myerror.h) */
jerr.addon_message_table = addon_message_table;
jerr.first_addon_message = JMSG_FIRSTADDONCODE;
jerr.last_addon_message = JMSG_LASTADDONCODE;
/* main loop */
for(PictureNr=0; PictureNr < NumPictures; PictureNr++)
{
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
if(PictureNr == NumPictures -1)
jpeg_destroy_decompress(&cinfo);
else
jpeg_abort_decompress(&cinfo);
if(infile)
{
Close(infile);
infile=0;
}
if(olddir)
{
CurrentDir(olddir);
olddir=0;
}
if(ColorCache)
{
free(ColorCache);
ColorCache=NULL;
}
if(MapFileName)
{
free(MapFileName);
MapFileName=NULL;
}
if(MapDirName)
{
free(MapDirName);
MapDirName=NULL;
}
if(ColorMapFile)
{
Close(ColorMapFile);
ColorMapFile=0;
}
if(OutputBuffer)
{
free(OutputBuffer);
OutputBuffer=NULL;
}
if(ScreenColorTable)
{
free(ScreenColorTable);
ScreenColorTable=NULL;
}
if(PictureNr == NumPictures -1 || WBFlags.SMRenable)
{
if(!ButtonPressed) FinalWait();
CloseDisplay();
if(finish) break;
}
if(finish)
{
CloseDisplay();
break;
}
else if(ButtonPressed)
DoNotWait=1;
continue;
}
/* CTRL-C handling) */
#ifdef __GNUC__
signal(SIGINT, interrupt);
#endif
if(olddir)
{
CurrentDir(olddir);
olddir=0;
}
ScaleFitDisplayID = 0;
if(WBFiles) memcpy(&WBFlags, &OldFlags, sizeof(struct WBFlags));
if(WBFiles && wb_arg)
{
if(wb_arg->wa_Name == NULL) ERREXIT(&cinfo, JERR_JPEGAGA_OPEN);
filename = wb_arg->wa_Name;
printf(" %s: ", filename);
fflush(stdout);
if(wb_arg->wa_Lock != 0)
{
olddir = CurrentDir(wb_arg->wa_Lock);
infile = Open(filename, MODE_OLDFILE);
if(infile) ParseToolTypes(wb_arg, 0);
}
else
{
infile = Open(filename, MODE_OLDFILE);
}
wb_arg++;
}
else if(!WBFiles)
{
filename = filenames[PictureNr];
printf(" %s: ", filename);
fflush(stdout);
infile = Open(filename, MODE_OLDFILE);
}
if(infile == 0)
{
ERREXIT(&cinfo, JERR_JPEGAGA_OPEN);
}
/* Step 2: specify data source (eg, a file) */
Amiga_jpeg_stdio_src(&cinfo, infile);
/* Step 3: read file parameters with jpeg_read_header() */
(void) jpeg_read_header(&cinfo, TRUE);
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
* See libjpeg.doc for more info.
*/
printf("%d x %d, ", (int)cinfo.image_width, (int)cinfo.image_height);
if(cinfo.progressive_mode) printf("progr., ");
fflush(stdout);
/* Step 4: set parameters for decompression */
/* set user selectable options */
if(WBFlags.DCTFast) cinfo.dct_method = JDCT_IFAST;
if(WBFlags.NoSmooth) cinfo.do_fancy_upsampling = FALSE; /* override this with options */
if(WBFlags.SMRenable)
{
int grayscale=0;
if(cinfo.out_color_space == JCS_GRAYSCALE) grayscale = 1;
FinalWait();
CloseDisplay();
if(finish) ERREXIT(&cinfo, JWRN_JPEGAGA_STOPPED);
if(ChooseScreenMode(grayscale, filename)) ERREXIT(&cinfo, JERR_JPEGAGA_NOMODE);
if(SMR_HAM)
WBFlags.GrayEnable = 0;
else
WBFlags.GrayEnable = 1;
}
else if(WBFlags.ScaleFit)
{
int tempscale;
if(WBFlags.GrayEnable) cinfo.out_color_space=JCS_GRAYSCALE; /* force grayscale output */
if(cinfo.out_color_space != JCS_GRAYSCALE)
Mode = HAM8;
else
Mode = 0;
tempscale = FindScaleFit(cinfo.image_width, cinfo.image_height, Mode);
if(tempscale == -1) ERREXIT(&cinfo, JERR_JPEGAGA_DISPLAY);
WBFlags.scale = tempscale;
}
if(WBFlags.GrayEnable) cinfo.out_color_space=JCS_GRAYSCALE; /* force grayscale output */
cinfo.scale_num = 1;
cinfo.scale_denom = (unsigned int)WBFlags.scale;
if(WBFlags.scale != 1) printf("scale 1/%d, ", WBFlags.scale);
/* Step 5: Start decompressor */
jpeg_start_decompress(&cinfo);
/* Now setup everything for showing the picture */
if(cinfo.out_color_space == JCS_GRAYSCALE)
{
printf("grayscale\n");
fflush(stdout);
ScreenColorTable = malloc(256*4*3+8);
if(!ScreenColorTable) ERREXIT(&cinfo, JERR_JPEGAGA_MEMORY);
for(i=0; i<256; i++)
{
ScreenColorTable[i*3+1] = (unsigned long)i<<24;
ScreenColorTable[i*3+2] = (unsigned long)i<<24;
ScreenColorTable[i*3+3] = (unsigned long)i<<24;
}
ScreenColorTable[0] = 256L<<16+0;
ScreenColorTable[256*3+1] = 0;
DisplaySuccess = InitDisplay(cinfo.output_width, cinfo.output_height, 0, 8);
if(finish) ERREXIT(&cinfo, JWRN_JPEGAGA_STOPPED);
if(ScreenColorTable)
{
free(ScreenColorTable);
ScreenColorTable=NULL;
}
if(DisplaySuccess != 1)
{
CloseDisplay();
ERREXIT(&cinfo, JERR_JPEGAGA_DISPLAY);
}
}
else if(cinfo.out_color_space == JCS_RGB)
{
printf("HAM8");
fflush(stdout);
ColorCache = calloc(262145, 1);
if(ColorCache == NULL) ERREXIT(&cinfo, JERR_JPEGAGA_MEMORY);
/* create the multiplication table */
for(i=-255; i<256; i++) Mult_Table[i+255] = (unsigned short)(i*i);
MapFileName = malloc(strlen(filename)+5);
if(MapFileName == NULL) ERREXIT(&cinfo, JERR_JPEGAGA_MEMORY);
strcpy(MapFileName, filename); /* create a copy of the file name */
strcat(MapFileName, ".map");
ColorMapFile = Open(MapFileName, MODE_OLDFILE);
/* try to find the file in the directory pointed to by the environment */
/* variable MAPDIR to support read-only devices like CD-ROM */
if(!ColorMapFile)
{
char *MapDir;
MapDir = getenv("MAPDIR");
if(MapDir)
if(strlen(MapDir) != 0)
{
int pos,i;
MapDirName = malloc(strlen(MapDir)+strlen(MapFileName)+5); /* worst case */
if(!MapDirName) ERREXIT(&cinfo, JERR_JPEGAGA_MEMORY);
strcpy(MapDirName, MapDir);
i = strlen(MapDirName);
if(MapDirName[i-1] != '/' && MapDirName[i-1] != ':')
{
strcat(MapDirName, "/");
i++;
}
i = strlen(MapFileName);
while(i > 0 && MapFileName[i-1] != '/' && MapFileName[i-1] != ':') i--;
strcat(MapDirName, &MapFileName[i]);
/* printf("%s\n", MapDirName); */
ColorMapFile = Open(MapDirName, MODE_OLDFILE);
}
}
if(!ColorMapFile)
{
int i = strlen(MapFileName) - 4;
while(i > 0 && MapFileName[i-1] != '.') i--;
if(MapFileName[i-1] == '.')
{
strcpy(&MapFileName[i], "map");
ColorMapFile = Open(MapFileName, MODE_OLDFILE);
}
}
if(ColorMapFile)
{
unsigned short MagicNumber;
unsigned int Reserved;
if(Read(ColorMapFile, &MagicNumber, 2) != 2) ERREXIT(&cinfo, JERR_JPEGAGA_MAPFILE);
if(MagicNumber != 0x1203) ERREXIT(&cinfo, JERR_JPEGAGA_MAPFILE);
if(Read(ColorMapFile, &Reserved, 4) != 4) ERREXIT(&cinfo, JERR_JPEGAGA_MAPFILE);
if(Read(ColorMapFile, ColorTable, 64*3) != 64*3) ERREXIT(&cinfo, JERR_JPEGAGA_MAPFILE);
printf(" with mapfile\n");
Close(ColorMapFile);
ColorMapFile = 0;
}
else
{
printf(", create a colormap file for better quality!\n");
memcpy(ColorTable, FixedColorTable, 64*3);
}
if(MapFileName)
{
free(MapFileName);
MapFileName=NULL;
}
if(MapDirName)
{
free(MapDirName);
MapDirName=NULL;
}
ScreenColorTable = malloc(64*4*3+8);
if(!ScreenColorTable) ERREXIT(&cinfo, JERR_JPEGAGA_MEMORY);
for(i=0; i<64; i++)
{
ScreenColorTable[i*3+1] = (unsigned long)ColorTable[i*3+1]<<26;
ScreenColorTable[i*3+2] = (unsigned long)ColorTable[i*3+2]<<26;
ScreenColorTable[i*3+3] = (unsigned long)ColorTable[i*3]<<26;
}
ScreenColorTable[0] = 64L<<16+0;
ScreenColorTable[64*3+1] = 0;
DisplaySuccess = InitDisplay(cinfo.output_width, cinfo.output_height, HAM8, 8);
if(finish) ERREXIT(&cinfo, JWRN_JPEGAGA_STOPPED);
if(ScreenColorTable)
{
free(ScreenColorTable);
ScreenColorTable=NULL;
}
if(DisplaySuccess != 1)
{
CloseDisplay();
ERREXIT(&cinfo, JERR_JPEGAGA_DISPLAY);
}
}
else ERREXIT(&cinfo, JERR_CONVERSION_NOTIMPL);
/* JSAMPLEs per row in output buffer */
/* make it a bit larger to allow direct screen output */
row_stride = (((cinfo.output_width * cinfo.output_components +15)>>4)<<4);
/* Make a sample array that will go away when done with image */
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, cinfo.rec_outbuf_height);
/* printf("Recommended size: %d\n", cinfo.rec_outbuf_height); */
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Here we use the library's state variable cinfo.output_scanline as the
* loop counter, so that we don't have to keep track ourselves.
*/
ButtonPressed=0;
if(cinfo.out_color_space == JCS_GRAYSCALE)
{
JDIMENSION numpixels, i;
while (cinfo.output_scanline < cinfo.output_height)
{
numpixels = jpeg_read_scanlines(&cinfo, buffer, cinfo.rec_outbuf_height);
if(CheckButton())
{
ButtonPressed=1;
ERREXIT(&cinfo, JWRN_JPEGAGA_STOPPED);
}
/* Assume put_scanline_someplace wants a pointer and sample count. */
for(i=0; i<numpixels; i++)
DisplayRow(buffer[i], cinfo.output_width);
}
}
else if(cinfo.out_color_space == JCS_RGB)
{
JDIMENSION numpixels, i;
#ifdef DEBUGFILE
FILE *testfile;
testfile = fopen("test.ppm", "w");
if(testfile == NULL) ERREXIT(&cinfo, JERR_JPEGAGA_MEMORY);
fprintf(testfile, "P6\n%ld %ld\n%d\n",
(long) cinfo.output_width, (long) cinfo.output_height, 255);
#endif
OutputBuffer = malloc(((cinfo.output_width+15)>>4)<<4);
if(!OutputBuffer) ERREXIT(&cinfo, JERR_JPEGAGA_MEMORY);
while (cinfo.output_scanline < cinfo.output_height)
{
numpixels = jpeg_read_scanlines(&cinfo, buffer, cinfo.rec_outbuf_height);
if(CheckButton())
{
ButtonPressed=1;
ERREXIT(&cinfo, JWRN_JPEGAGA_STOPPED);
}
/* Assume put_scanline_someplace wants a pointer and sample count. */
for(i=0; i<numpixels; i++)
{
#ifdef DEBUGFILE
fwrite(buffer[i], 3, cinfo.output_width, testfile);
#endif
EncodeHAM8(buffer[i], OutputBuffer, cinfo.output_width);
DisplayRow(OutputBuffer, cinfo.output_width);
}
}
#ifdef DEBUGFILE
fclose(testfile);
#endif
free(OutputBuffer);
OutputBuffer = NULL;
}
/* Step 7: Finish decompression */
(void) jpeg_finish_decompress(&cinfo);
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
*/
/* Step 8: Release JPEG decompression object */
#ifdef __GNUC__
signal(SIGINT, SIG_IGN);
#endif
/* This is an important step since it will release a good deal of memory. */
if(PictureNr == NumPictures -1) jpeg_destroy_decompress(&cinfo);
/* After finish_decompress, we can close the input file.
* Here we postpone it until after no more JPEG errors are possible,
* so as to simplify the setjmp error logic above. (Actually, I don't
* think that jpeg_destroy can do an error exit, but why assume anything...)
*/
if(olddir)
{
CurrentDir(olddir);
olddir=0;
}
if(infile)
{
Close(infile);
infile=0;
}
if(ColorCache)
{
free(ColorCache);
ColorCache=NULL;
}
DoNotWait=0;
if(PictureNr == NumPictures -1)
{
FinalWait();
CloseDisplay();
}
if(finish) break;
/* At this point you may want to check to see whether any corrupt-data
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
*/
/* And we're done! */
}
CloseDisplay(); /* just for the case we forgot to close something */
return 0;
}
static void Usage(void)
{
printf("Usage: jpegAGA [switches] [files]\n"
"switches: -gray force grayscale output\n"
" -fit scale output to fit on the screen\n"
" -scale M/N scale output image by fraction M/N, eg. 1/8\n"
" -nosmooth don't use high quality upsampling\n"
" -dct fast use fast integer DCT (less accurate)\n"
" -vga use VGA screenmode\n"
" -super72 use SUPER72 mode for large pictures\n"
" -smr use screen mode requester\n"
" -maxmem N maximum memory to use (for decoder)\n");
CloseDisplay();
exit(10);
}
int main(int argc, char *argv[])
{
int i;
#ifdef __GNUC__
signal(SIGINT, SIG_IGN); /* disable CTRL-C handling */
#endif
printf("jpegAGA 2.2 by Günther Röhrich. This program is Public Domain.\n");
/* remove the comments for beta versions */
/* printf("Preliminary version. DO NOT SPREAD IT!\n"); */
if(argc == 0 && argv) FillWB(argv);
else for(i=1; i<argc; i++)
{
if(MYSTRNCMP(argv[i], "-", 1))
{
FillNameBuffer(argv[i]);
continue;
}
#ifndef __GNUC__
strupr(argv[i]);
#endif
if(!MYSTRNCMP(argv[i], "-GRAY", 5)) WBFlags.GrayEnable=1;
else if(!MYSTRNCMP(argv[i], "-VGA", 4)) WBFlags.VGAenable=1;
else if(!MYSTRNCMP(argv[i], "-SUPER72", 8)) WBFlags.SUPER72enable=1;
else if(!MYSTRNCMP(argv[i], "-SMR", 4)) WBFlags.SMRenable=1;
else if(!MYSTRNCMP(argv[i], "-NOSMOOTH", 9)) WBFlags.NoSmooth=1;
else if(!MYSTRNCMP(argv[i], "-FIT", 4)) WBFlags.ScaleFit=1;
else if(!MYSTRNCMP(argv[i], "-DCT", 4))
{
if(argc == i+1) Usage(); /* last argument */
i++;
if(!MYSTRNCMP(argv[i], "FAST", 3)) WBFlags.DCTFast=1;
else if(!MYSTRNCMP(argv[i], "INT", 3)) WBFlags.DCTFast=0;
}
else if(!MYSTRNCMP(argv[i], "-SCALE", 6))
{
if(argc == i+1) Usage(); /* last argument */
i++;
if(!MYSTRNCMP(argv[i], "1/1", 3)) WBFlags.scale=1;
else if(!MYSTRNCMP(argv[i], "1/2", 3)) WBFlags.scale=2;
else if(!MYSTRNCMP(argv[i], "1/4", 3)) WBFlags.scale=4;
else if(!MYSTRNCMP(argv[i], "1/8", 3)) WBFlags.scale=8;
else Usage();
}
else if(!MYSTRNCMP(argv[i], "-MAXMEM", 7))
{
char ch = 'x';
if(argc == i+1) Usage(); /* last argument */
i++;
if (sscanf(argv[i], "%ld%c", &WBFlags.MaxMem, &ch) < 1) Usage();
if (ch == 'm' || ch == 'M') WBFlags.MaxMem *= 1000L;
WBFlags.MaxMemFlag = 1;
}
else Usage();
}
if(NumPictures == 0) ChooseFiles();
if(NumPictures == 0)
{
CloseDisplay();
FreeASL();
exit(10);
}
while(NumPictures)
{
read_JPEG_file(PicArray);
finish=0;
for(i=0; i<NumPictures; i++)
{
free(PicArray[i]);
PicArray[i]=NULL;
}
NumPictures=0;
if(ASLPicSelect) ChooseFiles();
}
CloseDisplay();
FreeASL();
return 0;
}